package com.lagou.edu.common.util;

import net.sf.cglib.beans.BeanCopier;

import java.lang.reflect.Field;
import java.lang.reflect.ReflectPermission;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 拷贝对象属性
 *
 * @author lm
 * @since 2021/10/12 15:08
 */
public class ConverUtil {
    /**
     * 将原对象的属性值，拷贝到目标对象对应的属性中
     *
     * @param source 原对象
     * @param target 目标对象
     * @param <S>
     * @param <T>
     * @return 属性拷贝完成的目标对象
     */
    public static <S, T> T convert(S source, T target) {
        if (source == null || target == null) {
            return null;
        }
        BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
        copier.copy(source, target, null);
        return target;
    }

    public static void main(String[] args) {

    }

    public static <S, T> T convert(S source, Class<T> target) {
        try {
            return convert(source, target.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 拷贝列表
     */
    public static <S, T> List<T> convertList(List<S> source, Class<T> target) {
        if (source == null) {
            return null;
        }
        return source.stream().map(item -> {
            T result = null;
            try {
                result = target.newInstance();
                convert(item, result);
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
            return result;
        }).collect(Collectors.toList());
    }

    /**
     * 将源对象的属性值复制到目标对象中
     *
     * @param type            对象类型
     * @param sourceBean      源对象
     * @param destinationBean 目标对象
     */
    public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
        Class<?> parent = type;
        while (parent != null) {
            final Field[] fields = parent.getDeclaredFields();
            for (Field field : fields) {
                try {
                    try {
                        // 把源对象的属性值设置到目标对象属性中
                        field.set(destinationBean, field.get(sourceBean));
                    } catch (IllegalAccessException e) {
                        if (canControlMemberAccessible()) {
                            // 设置访问权限
                            field.setAccessible(true);
                            field.set(destinationBean, field.get(sourceBean));
                        } else {
                            throw e;
                        }
                    }
                } catch (Exception e) {
                    // Nothing useful to do, will only fail on final fields, which will be ignored.
                }
            }
            // 获取父类
            parent = parent.getSuperclass();
        }
    }

    /**
     * 将源对象的属性值复制到目标对象中
     *
     * @param sourceBean      源对象
     * @param destinationBean 目标对象
     * @param fieldName 要拷贝的属性
     */
    public static <S, T> void copyBeanProperties(T sourceBean, S destinationBean, String fieldName) {
        Class<?> clazz = destinationBean.getClass();
        try {
            Field field = clazz.getField(fieldName);
            try {
                // 把源对象的属性值设置到目标对象属性中
                field.set(destinationBean, field.get(sourceBean));
            } catch (IllegalAccessException e) {
                if (canControlMemberAccessible()) {
                    // 设置访问权限
                    field.setAccessible(true);
                    field.set(destinationBean, field.get(sourceBean));
                } else {
                    throw e;
                }
            }
        } catch (Exception e) {

        }
    }

    /**
     * Checks whether can control member accessible.
     *
     * @return If can control member accessible, it return {@literal true}
     * @since 3.5.0
     */
    public static boolean canControlMemberAccessible() {
        try {
            SecurityManager securityManager = System.getSecurityManager();
            if (null != securityManager) {
                securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
            }
        } catch (SecurityException e) {
            return false;
        }
        return true;

    }
}




